//////////////////////////////////////////
// VECTOR CLASS							//
//////////////////////////////////////////
/**
 * Represents a basic 2D vector, as well as provides some
 * basic math convienance functions.
 */

export class Vector {
    constructor(x, y) {
        this.x = x;
        this.y = y;

        // 这两个是常量
        this.radsToDesc = 57.2957795;
        this.degsToRads = 0.0174532925;
    }

    clone() {
        return new Vector(this.x, this.y);
    }
    toAngle() {
        var angle = Math.atan2(this.y, this.x);
        return angle < 0 ? angle + 2 * Math.PI : angle;
    }
    toDegrees() {
        return this.toAngle() * this.radsToDesc;
    }
    length() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    }
    normalize() {
        var len = this.length();
        return len != 0 ? new Vector(this.x / len, this.y / len) : this;
    }
    fromAngle(radians) {
        this.x = Math.cos(radians);
        this.y = Math.sin(radians);
    }
    fromDegrees(degrees) {
        this.fromAngle(degrees * this.degsToRads);
    }
    scale(amount) {
        return new Vector(this.x * amount, this.y * amount);
    }
    getDistance(point) {
        return Math.sqrt(
            Math.pow(point.x - this.x, 2) + Math.pow(point.y - this.y, 2)
        );
    }
    getDirectionTo(point) {
        return new Vector(point.x - this.x, point.y - this.y).normalize();
    }

    add(amount) {
        return new Vector(this.x + amount.x, this.y + amount.y);
    }
    dot(vector) {
        return this.x * vector.x + this.y * vector.y;
    }

    inplaceAdd(amount) {
        this.x += amount.x;
        this.y += amount.y;
    }
    getClosestPointOnLine(start, end) {
        var delta = new Vector(end.x - start.x, end.y - start.y);

        if (delta.x == 0 && delta.y == 0) {
            return start;
        } else {
            var dist =
                ((this.x - start.x) * delta.x + (this.y - start.y) * delta.y) /
                (delta.x * delta.x + delta.y * delta.y);
            dist = Math.min(Math.max(0, dist), 1);

            return new Vector(
                start.x + dist * delta.x,
                start.y + dist * delta.y
            );
        }
    }
}
